package com.cwf.framework.log.aspectj;

import com.alibaba.fastjson2.JSON;
import com.cwf.common.core.controller.BaseController;
import com.cwf.common.entity.auth.TokenInfo;
import com.cwf.common.utils.ip.IpUtils;
import com.cwf.framework.log.entity.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;


@Slf4j
@Aspect
@Component
public class LogAspect extends BaseController {


    /**
     * 统计请求的处理时间
     */
    ThreadLocal<Long> startTime = new ThreadLocal<>();


    /**
     * @methodName：exceptionLogPoinCut
     * @description：设置操作异常切入点记录异常日志 扫描所有controller包下操作
     * @author：tanyp
     * @dateTime：2021/11/18 14:22
     * @Params： []
     * @Return： void
     * @editNote：
     */
    @Pointcut("execution(public * com.cwf.*.controller.*.*(..))")
    public void logPointcut() {
    }

    @Before("logPointcut()")
    public void doBefore() {
        // 接收到请求，记录请求开始时间
        startTime.set(new Date().getTime());
    }


    /**
     * @param joinPoint
     */
    @AfterReturning(value = "logPointcut()",returning = "data")
    public void doAround(JoinPoint joinPoint,Object data) {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);


        TokenInfo userInfo = getUserInfo();

        SysLog logInfo = new SysLog();
        try {
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();

            // 获取切入点所在的方法
            Method method = signature.getMethod();

            // 获取请求的类名
            String className = joinPoint.getTarget().getClass().getName();

            logInfo.setId(UUID.randomUUID().getMostSignificantBits());
            //请求的方法名位置
            String methodStr = "["+request.getMethod()+"] "+className + "." + method.getName();
            logInfo.setMethod(methodStr);


            String userId = userInfo.getUserId();
            logInfo.setUserId(userId); // 请求用户ID

            String userName = userInfo.getUserName();
            logInfo.setUserName(userName); // 请求用户名称

            String path = request.getRequestURI();
            logInfo.setPath(path); // 请求路径

            String parameter = JSON.toJSONString(joinPoint.getArgs());
            logInfo.setParameter(parameter); //请求参数

            String ip = IpUtils.getIpAddress(request);
            logInfo.setIp(ip); // 请求IP

            Long task = new Date().getTime()-startTime.get();
            logInfo.setTaskTime(task);


            String res = JSON.toJSONString(data);

            log.info(
                    "\n用户id: {}" +
                    "\n用户名: {}" +
                    "\n路径: {}"+
                    "\n方法: {}"+
                    "\n参数: {}"+
                    "\nip: {}"+
                    "\n耗时: {}(毫秒)"+
                    "\n响应数据: {}",
                    userId,userName,path,methodStr,parameter,ip,task,res
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
